﻿Imports System.Collections.ObjectModel
Imports System.Collections.Specialized

Namespace Load

    ''' <summary>
    ''' 遅延読み込みリスト
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <remarks>
    ''' #102 LazyListをObservableCollection型継承に変える
    ''' </remarks>
    Public Class LazyList(Of T)
        Inherits ObservableCollection(Of T)
        Implements ILazy
        Implements IFetchQueryRoot(Of T)

        ''' <summary>
        ''' コンストラクタ
        ''' </summary>
        ''' <param name="q"></param>
        ''' <remarks>
        ''' #102 LazyListをObservableCollection型継承に変える
        ''' コンストラクタの引数を見直し。
        ''' </remarks>
        Public Sub New(q As Query(Of T))
            Me.Query = q
        End Sub

        ''' <summary>
        ''' モデルローダー
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>
        ''' #102 LazyListをObservableCollection型継承に変える
        ''' Queryに登録されているLoaderを使用することで統一
        ''' </remarks>
        Friend ReadOnly Property Loader As ModelLoader
            Get
                Return Me.Query.Provider.Loader
            End Get
        End Property

        ''' <summary>
        ''' 取得クエリ
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Property Query As Query(Of T)

#Region "ILazy"
        ''' <summary>
        ''' コレクションを取得します
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Fetch() Implements ILazy.Fetch
            If Me.IsFetched Then Return
            If Me.Loader.Connection.State = ConnectionState.Closed Then Throw New TooLateLazyLoadException

            _isFetched = True

            For Each item As T In Me.Query.ToList
                Me.Add(item)
            Next
        End Sub

        Private _isFetched As Boolean = False
        ''' <summary>
        ''' 取得済みかどうかを示します
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property IsFetched As Boolean Implements ILazy.IsFetched
            Get
                Return If(Me.Any OrElse _isFetched, True, False)
            End Get
        End Property
#End Region

        ''' <summary>
        ''' 初期化します
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shadows Function Clear() As LazyList(Of T)
            Me.ClearItems()
            Return Me
        End Function

        ''' <summary>
        ''' 初期化します
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
            'Fetch状態も初期化します
            _isFetched = False
        End Sub

#Region "IFetchQueryRoot"
        Public Function ToQuery() As FetchQuery(Of T) Implements IFetchQueryRoot(Of T).ToQuery
            Return New FetchQuery(Of T)(Me.Loader.From(Of T).Provider, Me)
        End Function

        Public Function Batch() As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).Batch
            Me.Loader.Batch()
            Return Me
        End Function

        Public Function Cascade(level As Integer) As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).Cascade
            Me.Loader.Cascade(level)
            Return Me
        End Function

        Public Function FullCascade() As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).FullCascade
            Me.Loader.FullCascade()
            Return Me
        End Function

        Public Function IncludeOuter() As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).IncludeOuter
            Me.Loader.IncludeOuter()
            Return Me
        End Function

        Public Function InnerOnly() As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).InnerOnly
            Me.Loader.InnerOnly()
            Return Me
        End Function

        Public Function Iterate() As LazyList(Of T) Implements IQueryRoot(Of LazyList(Of T)).Iterate
            Me.Loader.Iterate()
            Return Me
        End Function

        Public Sub ResetQueryType() Implements IQueryRoot(Of LazyList(Of T)).ResetQueryType
            Me.Loader.ResetQueryType()
        End Sub
#End Region

    End Class

End Namespace
